﻿// Copyright (c) Inossem. All rights reserved.
// Licensed under the LGPL-3.0 license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DWF.Studio.ScriptEngine.Custom
{
    internal class ArgumentsHandler : IDisposable
    {
        private const int FileSize = 1024 * 1024;

        private const string FileName = "ProcessGo_ScriptEngine_Arguments";

        private const string MutexName = "ProcessGo_ScriptEngine_Mutex";

        private Mutex _mutex = null;

        private MemoryMappedFile _memoryMappedFile = null;

        public static readonly ArgumentsHandler Instance = new ArgumentsHandler();

        private ArgumentsHandler()
        {
            _memoryMappedFile = MemoryMappedFile.CreateOrOpen(FileName, FileSize, MemoryMappedFileAccess.ReadWrite);
            if (!Mutex.TryOpenExisting(MutexName, out this._mutex))
            {
                this._mutex = new Mutex(false, MutexName);
            }
        }

        public string GetArguments()
        {
            string result = null;

            _mutex.WaitOne();
            using (MemoryMappedViewStream memoryMappedViewStream = _memoryMappedFile.CreateViewStream(0, FileSize))
            {
                using (BinaryReader binaryReader = new BinaryReader(memoryMappedViewStream, Encoding.UTF8))
                {
                    result = binaryReader.ReadString();
                }
            }
            _mutex.ReleaseMutex();

            return result;
        }

        public void SetArguments(string arguments)
        {
            _mutex.WaitOne();
            using (MemoryMappedViewStream memoryMappedViewStream = _memoryMappedFile.CreateViewStream())
            {
                using (BinaryWriter binaryWriter = new BinaryWriter(memoryMappedViewStream, Encoding.UTF8))
                {
                    binaryWriter.Write(arguments);
                }
            }
            _mutex.ReleaseMutex();
        }

        #region IDisposable Support
        private bool disposedValue = false; // 要检测冗余调用

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: 释放托管状态(托管对象)。
                    _mutex.Dispose();
                    _memoryMappedFile.Dispose();
                }

                // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
                // TODO: 将大型字段设置为 null。

                disposedValue = true;
            }
        }

        // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
        // ~PipeNameHandler()
        // {
        //   // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
        //   Dispose(false);
        // }

        // 添加此代码以正确实现可处置模式。
        public void Dispose()
        {
            // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
            Dispose(true);
            // TODO: 如果在以上内容中替代了终结器，则取消注释以下行。
            // GC.SuppressFinalize(this);
        }
        #endregion
    }
}
